use std::{num::ParseIntError, str::Utf8Error, string::FromUtf8Error};

use thiserror::Error;

use crate::serialport::address;

pub type IoErr = std::io::Error;
pub type SqlxErr = sqlx::Error;


#[derive(Debug, Error)]
pub enum AppErr {

    #[error("io:{0}")]
    Io(#[from] IoErr),
    
    #[error("jni:{0}")]
    Jni(#[from] jni::errors::Error),

    #[error("utf8:{0}")]
    Utf8(#[from] Utf8Error),

    #[error("utf8:{0}")]
    Utf8_(#[from] FromUtf8Error),

    #[error("{0}")]
    Static(&'static str),

    #[error("{0}")]
    Dyn(String),

    #[error("sqlx:{0}")]
    Sqlx(#[from] SqlxErr),

    #[error("sp:{0}")]
    SerialPort(#[from] tokio_serial::Error),

    #[error("BytesRejection:{0}")]
    BytesRejection(#[from] axum::extract::rejection::BytesRejection),

    #[error("cbor{0}")]
    Cbor(#[from] serde_cbor::Error),

    #[error("json:{0}")]
    Json(#[from] serde_json::Error),

    #[error("reqwest:{0}")]
    Reqwest(#[from] reqwest::Error),

    #[error("http_film: {0}")]
    HttpFilm(i32),

    #[error("mac:{0}")]
    MacAddr(#[from] mac_address2::MacAddressError),

    #[error("robot closed")]
    RobotClosed,

    #[error("robot net:{0}")]
    RobotNet(&'static str),

    #[error("robot service:{0}")]
    RobotService(&'static str),

    #[error("parse:{0}")]
    Parse(#[from] ParseIntError),

    #[error("base:{0}")]
    Base(&'static str),

    #[error("货架:{0}")]
    Cargo(&'static str),

    #[error("切膜落杯:{0}")]
    Drop(&'static str),

    #[error("加热控制:{0}")]
    Heat(&'static str),
}

pub fn new_error(msg: &'static str) -> AppErr {
    AppErr::Static(msg)
}

pub fn parse_ec(src: u8, ec: u8) -> AppErr {
    match ec {
        0 => panic!("ec is ok"),
        1 => AppErr::Base("OTA Flash错误"),
        2 => AppErr::Base("OTA Id错误"),
        3 => AppErr::Base("OTA Md5错误"),
        4 => AppErr::Base("OTA Size错误"),
        5 => AppErr::Base("无效的CMD"),
        6 => AppErr::Base("解析参数错误"),
        7 => AppErr::Base("无效的参数"),
        _ => {
            match src {
                address::CARGO1 | address::CARGO2 => parse_cargo_ec(ec),
                address::DROP => parse_drop(ec),
                address::HEAT => parse_heat(ec),
                _ => AppErr::Base("Unknown src")
            }
        }
    }
}

fn parse_heat(ec: u8) -> AppErr {
    match ec {
        0x11 => AppErr::Heat("温度传感器故障"),
        0x12 => AppErr::Heat("移动电机堵转"),
        0x13 => AppErr::Heat("移动电机超时"),
        0x14 => AppErr::Heat("搅拌盖堵转"),
        0x15 => AppErr::Heat("搅拌盖超时"),
        0x16 => AppErr::Heat("截流堵转"),
        0x17 => AppErr::Heat("截流超时"),
        _ => AppErr::Heat("Unknown Error"),
    }
}

fn parse_drop(ec: u8) -> AppErr {
    match ec {
        0x11 => AppErr::Drop("落杯1超时"),
        0x12 => AppErr::Drop("落杯2超时"),
        0x13 => AppErr::Drop("落杯3超时"),
        0x14 => AppErr::Drop("封膜 没有杯子"),
        0x15 => AppErr::Drop("封膜 超时"),
        0x16 => AppErr::Drop("切膜超时"),
        0x17 => AppErr::Drop("切膜堵转"),
        _ => AppErr::Static("Unknown Error"),
    }
}

fn parse_cargo_ec(ec: u8) -> AppErr {
    match ec {
        0x11 => AppErr::Cargo("取货电机堵转"),
        0x12 => AppErr::Cargo("取货电机超时"),
        0x13 => AppErr::Cargo("货架电机堵转"),
        0x14 => AppErr::Cargo("货架电机超时"),
        0x15 => AppErr::Cargo("扫码超时"),
        0x16 => AppErr::Cargo("扫码数据错误"),
        0x17 => AppErr::Cargo("气缸上去失败"),
        0x18 => AppErr::Cargo("气缸下去失败"),
        0x19 => AppErr::Cargo("转入内部失败"),
        0x1A => AppErr::Cargo("转入外部失败"),
        0x1B => AppErr::Cargo("抓取失败"),
        _ => AppErr::Static("Unknown Error")
    }
}

pub fn pase_err(src: u8, ec: u8) -> Result<(), AppErr> {
    match ec {
        0 => Ok(()),
        _ => Err(parse_ec(src, ec))
    }
}
